﻿//////////////////////////////////////////////////////////////////////////////
//
//  Copyright © 1998-2024 Glodon Company Limited.  All rights reserved.
//
//  Use of this software is subject to the terms of the Glodon license
//  agreement provided at the time of installation or download, or which
//  otherwise accompanies this software in either electronic or hard copy form.  
//
//////////////////////////////////////////////////////////////////////////////

// Reviewed

#pragma once

#include "ISurface.h"
#include "GeometryErrorCode.h"


namespace gcmp
{
    class IPlane;
    class ISurface;
    class IPolygon;
    class ICurve2d;
    class ICurve3d;
    class IBody;
    struct NurbsSurfaceCtrlPt3d;

    enum class SurfaceCurvatureType : int8_t
    {
        MaxCurvature = 1,                       //最大曲率
        FabsMaxCurvature = 2,                   //曲率的绝对值的最大值   
        MinCurvature = 3,                       //最小曲率
        FabsMinCurvature = 4,                   //曲率的绝对值的最小值
        MeanCurvature = 5,                      //平均曲率
        GaussCurvature = 6,                     //高斯曲率
    };

    class ISurfaceOperate
    {
    public:
        virtual ~ISurfaceOperate() {}

        /// \brief  曲面切分曲面(目前仅处理一切为二的情形)
        ///
        /// \param pTrimmedSurface            被切曲面
        /// \param pTrimTool                  切割工具曲面
        /// \param opPositiveSurface          被切曲面在切割工具曲面的正法向部分(切割工具曲面封闭如柱面，则柱面外为正向，柱面内为负向)
        /// \param opNegativeSurface          被切曲面在切割工具曲面的负法向部分
        /// \return true 成功; false 失败
        /// \note 部分切割返回false
        virtual bool TrimSurface(const ISurface* pTrimmedSurface,
            const ISurface* pTrimTool,
            OwnerPtr<ISurface>&  opPositiveSurface,
            OwnerPtr<ISurface>&  opNegativeSurface)const = 0;

        /// \brief 可展曲面展开，展开平面坐标系：S(u0,v0)为原点，固定起始边界直母线为Y轴，导线起点切向为X轴
        /// \param[in]  pSurface       可展曲面
        /// \param[in]  pCurve3d       可展曲面上的三维曲线
        /// \param[out] opBoundary     可展曲面展开后的曲面边界多边形
        /// \param[out] opCurve2d      三维曲线展开后的二维曲线
        /// \param[in]  dDistEpsilon   曲线拟合距离误差。GGP全局距离容差最小为1e-4，这里的容差不能小于全局距离容差。这里的输入容差主要用于离散与反求参数等。
        /// \return 展为平面是否成功, true 是; false 不是
        virtual bool FlattenSurface(const ISurface* pSurface, const ICurve3d *pCurve3d, OwnerPtr<IPolygon>& opBoundary, OwnerPtr<ICurve2d>& opCurve2d, double dDistEpsilon)const = 0;

        /// \brief Brep体上的某个Face展开，只支持可展曲面，plane,Cylinder,Bevel
        /// \param[in]  pBody           输入的Brep体
        /// \param[in]  iFaceIndex      Brep体上需要展开的Face的索引
        /// \param[out] opFaceBoundary  可展曲面展开后的对应的Face边界多边形
        /// \param[in]  dDistEpsilon    曲线拟合距离误差。GGP全局距离容差最小为1e-4，这里的容差不能小于全局距离容差。这里的输入容差主要用于离散与反求参数等。
        /// \return 展为平面是否成功, true 是; false 不是
        virtual bool FlattenFace(const IBody *pBody, int iFaceIndex, OwnerPtr<IPolygon>& opFaceBoundary, double dDistEpsilon)const = 0;
        

        /// \brief  调整给定Sheet壳体的Nurbs面的指定控制点，更新给定Sheet壳体
        ///
        /// 输入的SheetBody只有一个face，且face的surface为nurbs类型，否则编辑失败
        /// \param[in,out] pSheetBody          待更新的SheetBody
        /// \param[in]  uIndex                 u向索引号
        /// \param[in]  vIndex                 v向索引号
        /// \param[in]  newCtrlPt              更新后的控制点
        /// \return   错误码，失败提示信息
        virtual GeometryErrorCode NurbsMoveControlPoint(IBody *pSheetBody, int uIndex, int vIndex, const NurbsSurfaceCtrlPt3d& newCtrlPt)const = 0;

        // \brief   插入给定Sheet壳体的Nurbs面的节点矢量，更新给定Sheet壳体
        ///
        /// 输入的SheetBody只有一个face，且face的surface为nurbs类型，否则编辑失败
        /// \param[in,out] pSheetBody          待更新的SheetBody
        /// \param[in]  uDir                   u向 or v向
        /// \param[in]  knotValue              插入的节点值
        /// \param[in] count                   插入重节点次数
        /// \return   错误码，失败提示信息
        virtual GeometryErrorCode NurbsInsertKnot(IBody *pSheetBody, bool uDir, double knotValue, int count)const = 0;

        // \brief   增加给定Sheet壳体的Nurbs面的一排控制顶点，更新给定Sheet壳体
        ///
        /// 输入的SheetBody只有一个face，且face的surface为nurbs类型，否则编辑失败
        /// \param[in,out] pSheetBody          待更新的SheetBody
        /// \param[in]  uDir                   u向 or v向的一排控制顶点
        /// \param[in]  pt                     曲面上一点
        /// \param[in,out] insertCtrlPts       返回插入的控制顶点
        /// \param[in,out] knotValue           返回插入的节点值，若uDir，则为v向节点值
        /// \return   错误码，失败提示信息
        virtual GeometryErrorCode NurbsInsertControlPoints(IBody *pSheetBody, bool uDir, const Vector3d &pt, std::vector<NurbsSurfaceCtrlPt3d> *insertCtrlPts, double *knotValue)const = 0;

        // \brief   删除给定Sheet壳体的Nurbs面的一排控制顶点，更新给定Sheet壳体
        ///
        /// 输入的SheetBody只有一个face，且face的surface为nurbs类型，否则编辑失败
        /// \param[in,out] pSheetBody          待更新的SheetBody
        /// \param[in]  uDir                   u向 or v向
        /// \param[in]  ctrlPtIndex            删除控制点对应index
        /// \return   错误码，失败提示信息
        virtual GeometryErrorCode NurbsRemoveControlPoints(IBody *pSheetBody, bool uDir, int ctrlPtIndex)const = 0;

        // \brief   求解指定点在曲面的绝对值最大曲率，绝对值最小曲率，最大曲率，最小曲率，平均曲率，高斯曲率
        ///
        /// \param[in] pSurface          点所在曲面
        /// \param[in] dU                指定点的U参数值
        /// \param[in] dV                指定点的V参数值
        /// \param[in] CurvatureFlag     指定的曲率类型
        /// \param[out] curvature     对应的曲率类型的值
        /// \return   错误码，失败提示信息
        virtual GeometryErrorCode CalculateSurfaceCurvature(const ISurface* pSurface, double dU, double dV, SurfaceCurvatureType CurvatureType, double &curvature) const = 0;
    };
}